package cn.wolfcode.shop.cloud.web.controller;

import cn.wolfcode.shop.cloud.common.BusinessException;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.OrderInfo;
import cn.wolfcode.shop.cloud.domain.SeckillOrder;
import cn.wolfcode.shop.cloud.domain.User;
import cn.wolfcode.shop.cloud.mq.MQConstants;
import cn.wolfcode.shop.cloud.mq.OrderMessage;
import cn.wolfcode.shop.cloud.redis.RedisService;
import cn.wolfcode.shop.cloud.redis.SecKillKeyPrefix;
import cn.wolfcode.shop.cloud.service.IOrderInfoService;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.service.ISeckillOrderService;
import cn.wolfcode.shop.cloud.util.ParamType;
import cn.wolfcode.shop.cloud.util.SeckillCodeMsg;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVO;
import com.netflix.discovery.converters.Auto;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.xml.crypto.Data;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@RestController
@RequestMapping("/order")
public class SeckillOrderController {
    @Autowired
    private ISeckillGoodService seckillGoodService;
    @Autowired
    private ISeckillOrderService seckillOrderService;
    @Autowired
    private IOrderInfoService orderInfoService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    //本地标识
    //ConcurrentHashMap分段锁将map分成了16份segment，但是每把都加了锁，性能比hashtable高，并发执行
    public static final ConcurrentHashMap<Long,Boolean> isFlag=new ConcurrentHashMap<>();

    /**
     * 该方法返回一个订单编号;
     * @param seckillId
     * @return
     */
    @RequestMapping("/{path}/doSeckill")
    public Result<String > doSeckill(Long seckillId, @PathVariable String path, String uuid, @ParamType User user){
        //1.参数校验
        //判断用户是否登录,如果没有提醒用户非法操作
        if(user==null){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        //判断路径是否合法
        String redisPath = redisService.get(SecKillKeyPrefix.SECKILL_PATH, uuid, String.class);
        if (redisPath==null){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
//如果本地是true说明进去人数已经够了
        Boolean flag = isFlag.get(seckillId);
        //flag!=null&&flag=true
        //如果本地已经是true那么说明已经过去足够人数
        if (flag!=null&&flag){
            //库存不够
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        //
        //根据秒杀商品的id上数据库去查询,看是否能够查询出数据没如果查询不到,提醒用户非法操作
        SeckillGoodVO goodVo = seckillGoodService.queryByIdCache(seckillId);
        if(goodVo==null){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        //判断秒杀时间是否在秒杀中,如果没有在秒杀中提醒用户;
        Date endDate = goodVo.getEndDate();
        Date startDate = goodVo.getStartDate();
        Date now = new Date();
        if(now.getTime()<startDate.getTime()||now.getTime()>endDate.getTime()){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        //判断用户是否重复下单
        //SeckillOrder order = seckillOrderService.selectByUserIdAndSeckillId(user.getId(), seckillId);
        boolean exists = redisService.exists(SecKillKeyPrefix.SECKILL_CREATE_ORDER, user.getId() + ":" + seckillId);
//有值直接返回true，用户已经下单过，抛出不能重复下单
        if(exists){
            throw new BusinessException(SeckillCodeMsg.SECKILL_ORDER_REPEAT);
        }
        /*//判断库存是否足够,如果不足提醒用户库存不足;
        if(goodVo.getStockCount()<=0){
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }*/


        //利用redis控制访问人数 KEY是秒杀商品的id
        long count = redisService.decr(SecKillKeyPrefix.SECKILL_STOCK_COUNT, seckillId + "");
        if (count<0){
            //redis已经存入了足够的人数
            isFlag.put(seckillId,true);
            //人数够了直接返回不在访问redis
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }


        //2.秒杀的业务逻辑
       // String  orderNo=orderInfoService.doSeckill(user.getId(),seckillId);
        //减少真实库存
        //创建订单对象保存到数据库中
        //往t_seckill_order表中插入一条数据

        //return Result.success(orderNo);

        //封装消息
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setSeckillId(seckillId);
        orderMessage.setSeckillId(user.getId());
        orderMessage.setUuid(uuid);
        //把消息发送到消息中间件中
        rocketMQTemplate.syncSend(MQConstants.CREATE_ORDER_DEST,orderMessage);

        return Result.success("正在抢购----");

    }





    @RequestMapping("getOrderInfoByOderNo")
    public Result<OrderInfo> getOrderInfoByOderNo(String orderNo,@ParamType User user){
        //判断用户是否登录
        if(user==null){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        OrderInfo orderInfo=orderInfoService.getOrderInfoByOderNo(orderNo);
        //判断订单编号
        if(orderInfo==null){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        //规定只有该订单的用户才能看到信息
        if(!orderInfo.getUserId().equals(user.getId())){
            throw new BusinessException(SeckillCodeMsg.SECKILL_OPT);
        }
        return Result.success(orderInfo);
    }
}
